<template>
  <el-dialog :visible.sync="dialogVisible" width="80%" :title="file.name">
    <el-scrollbar class="document-editor" style="height: 600px;">
      <el-button type="primary" @click="saveDocument" style="margin-bottom: 20px;">保存</el-button>
      <quill-editor v-model="editorContent" :options="editorOption" style="height: 400px;"></quill-editor>
    </el-scrollbar>
  </el-dialog>
</template>

<script>
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';

import { quillEditor } from 'vue-quill-editor';
import mammoth from 'mammoth';
import { saveAs } from 'file-saver';
import { Document, Packer, Paragraph, TextRun, HeadingLevel } from 'docx';

export default {
  name: "DocumentEditor",
  components: {
    quillEditor
  },
  props: {
    visible: {
      type: Boolean,
      required: true
    },
    file: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      editorContent: '',
      dialogVisible: this.visible,
      editorOption: {
        theme: 'snow'
      }
    };
  },
  watch: {
    visible(newVal) {
      this.dialogVisible = newVal;
    },
    dialogVisible(newVal) {
      if (!newVal) {
        this.$emit('update:visible', false);
      }
    },
    file(newFile) {
      if (newFile) {
        if(!newFile.raw) return
        this.loadDocument(newFile.raw);
      }
    }
  },
  methods: {
    async loadDocument(file) {
      const reader = new FileReader();
      reader.onload = async (event) => {
        const arrayBuffer = event.target.result;
        const result = await mammoth.convertToHtml({ arrayBuffer });
        this.editorContent = result.value;
      };
      reader.readAsArrayBuffer(file);
    },
    async saveDocument() {
      // 将 HTML 转换为 DOCX
      const doc = new Document({
        sections: [{
          properties: {},
          children: [
            ...this.htmlToDocx(this.editorContent)
          ]
        }]
      });

      // 使用 Packer 将 Document 对象转换为 .docx 文件并保存
      Packer.toBlob(doc).then(blob => {
        saveAs(blob, `${this.file.name}`);
        this.dialogVisible = false; // 关闭对话框
      });
    },
    htmlToDocx(htmlString) {
      const parser = new DOMParser();
      const doc = parser.parseFromString(htmlString, 'text/html');
      const elements = Array.from(doc.body.children);

      const convertElement = (element) => {
        switch (element.tagName.toLowerCase()) {
          case 'p':
            return new Paragraph({
              children: [new TextRun(element.innerText)]
            });
          case 'h1':
            return new Paragraph({
              text: element.innerText,
              heading: HeadingLevel.HEADING_1
            });
          case 'h2':
            return new Paragraph({
              text: element.innerText,
              heading: HeadingLevel.HEADING_2
            });
          case 'h3':
            return new Paragraph({
              text: element.innerText,
              heading: HeadingLevel.HEADING_3
            });
          case 'strong':
            return new Paragraph({
              children: [new TextRun({ text: element.innerText, bold: true })]
            });
          case 'em':
            return new Paragraph({
              children: [new TextRun({ text: element.innerText, italics: true })]
            });
          case 'ul':
            return element.children.map(li => {
              return new Paragraph({
                children: [new TextRun({ text: li.innerText, bullet: true })]
              });
            });
          case 'ol':
            return element.children.map((li, index) => {
              return new Paragraph({
                children: [new TextRun({ text: `${index + 1}. ${li.innerText}` })],
                alignment: AlignmentType.LEFT
              });
            });
          case 'img':
            return new Paragraph({
              children: [new ImageRun({
                data: element.src.split(',')[1], // Base64 encoded image data
                transformation: {
                  width: 200,
                  height: 200,
                },
              })]
            });
          default:
            return new Paragraph({
              children: [new TextRun(element.innerText)]
            });
        }
      };

      let children = [];
      for (let element of elements) {
        if (element.children.length > 0) {
          children.push(...element.children.flatMap(convertElement));
        } else {
          children.push(convertElement(element));
        }
      }

      return children.flat();
    }
  }
};
</script>

<style scoped>
.document-editor {
  padding: 20px;
}
</style>
